package com.mysher.http_server

import android.text.TextUtils
import android.util.Log
import com.koushikdutta.async.BufferedDataSink
import com.koushikdutta.async.http.Multimap
import com.koushikdutta.async.http.body.AsyncHttpRequestBody
import com.koushikdutta.async.http.server.AsyncHttpServer
import com.koushikdutta.async.http.server.AsyncHttpServerRequest
import com.koushikdutta.async.http.server.AsyncHttpServerResponse
import com.koushikdutta.async.http.server.HttpServerRequestCallback
import java.io.File
import java.io.IOException
import java.util.Locale


class LocalHttpServer :HttpServerRequestCallback{

    private val server by lazy { AsyncHttpServer() }

    val encode by lazy { Encode(1280,720,1280*720*3/2*15,15) }

    companion object{
        private const val TAG = "AsyncHttpServer"
        private var INSTANCE: LocalHttpServer? = null
        var PORT_LISTEN_DEF = 60001
        @JvmStatic
        fun get():LocalHttpServer{
            if (INSTANCE == null) {
                synchronized(LocalHttpServer::class.java) {
                    if (INSTANCE == null) {
                        INSTANCE = LocalHttpServer()
                    }
                }
            }
            return INSTANCE!!
        }

        @JvmStatic
        fun execCmd(cmd: String){
            try {
                Runtime.getRuntime().exec(cmd.replace("adb shell", ""))
            }catch (e: IOException){
                e.printStackTrace()
            }
        }
    }

    enum class Status(val requestStatus: Int, val description: String) {
        REQUEST_OK(200, "请求成功"), REQUEST_ERROR(500, "请求失败"), REQUEST_ERROR_API(
            501,
            "无效的请求接口"
        ),
        REQUEST_ERROR_CMD(502, "无效命令"), REQUEST_ERROR_DEVICEID(503, "不匹配的设备ID"), REQUEST_ERROR_ENV(
            504,
            "不匹配的服务环境"
        );

    }


    /*
        1）例如：server.addAction("OPTIONS", "[\d\D]", this)是通用的过滤请求的方法。第一个参数是请求的方法，例如用“OPTIONS”、“DELETE”、“POST”、“GET”等（注意用大写），第二个参数是过滤uri的正则表达式，此处是过滤所有的uri，第三个是回调参数。server.post("[\d\D]", this)、server.get("[\d\D]*", this)这个是上一个方法的特例。server.listen(PORT_LISTEN_DEFALT)这个是监听端口;
        2） request.getHeaders().getMultiMap()
        这个是获取header参数的地方，一定要谨记哦;
        3）(( AsyncHttpRequestBody<Multimap>)request.getBody()).get()这个地方是获取post请求的参数的地方;
        4）获取静态资源的代码是在回调方法onResponse的else中，例子如上。
        5）说一下OPTIONS的坑点，因为AndroidAsync这个框架中封装的返回http的状态码只有两种，假如过滤方法中没有包含例如OPTIONS的请求方法，实际上返回给客户端的http状态码是400，而反映到浏览器的报错信息竟然是跨域的问题，找了很久才找到，请注意。

        总结：
        1）同一个页面：
        NanoHttpd耗时：1.4s
        AndroidAsync耗时：1.4s
        但是在第二次进去的时候，AndroidAsync的耗时明显比第一个少了，笔者猜测是因为AndroidAsync底层做了一些处理。

        2）从api分析的话，NanoHttpd的用法比较方便，获取传递的参数那些的api比较好用；AndroidAsync的api就相对来说要复杂一些，例如params的获取。

        3）从场景来分析的话，如果需要并发量高的需求，一定要用AndroidAsync；但是如果不需要的话，那就再具体分析。
     */

    /**
     * 开启本地服务
     */
    fun startServer() {
        //如果有其他的请求方式，例如下面一行代码的写法
        server.addAction("OPTIONS", "[\\d\\D]*", this)
        server.get("[\\d\\D]*", this)
        server.post("[\\d\\D]*", this)
        server.listen(PORT_LISTEN_DEF)
        //execCmd("forward tcp:11111 tcp:5000")

    }

    override fun onRequest(request: AsyncHttpServerRequest?, response: AsyncHttpServerResponse?) {
        Log.d(TAG, "进来了，哈哈")
        val uri = request!!.path
        //这个是获取header参数的地方，一定要谨记哦
        val headers = request!!.headers.multiMap
        if (checkUri(uri)) { // 针对的是接口的处理
            //注意：这个地方是获取post请求的参数的地方，一定要谨记哦
            val parms = (request.body as AsyncHttpRequestBody<Multimap?>).get()
            if (headers != null) {
                Log.d(TAG, headers.toString())
            }
            if (parms != null) {
                Log.d(TAG, "parms = $parms")
            }
            if (TextUtils.isEmpty(uri)) {
                throw RuntimeException("无法获取请求地址")
            }
            if ("OPTIONS".lowercase(Locale.getDefault()) == request.method.toLowerCase()) {
                Log.d(TAG, "OPTIONS探测性请求")
                addCORSHeaders(Status.REQUEST_OK, response)
                return
            }
            return when (uri) {
//                "/test" -> {
//                    Log.i("ww","/test")
//                    //接口2
//                    //此方法包括了封装返回的接口请求数据和处理异常以及跨域
//                    //val file = File("sdcard/w7-web/w7/W7-zh.html")
//                    response!!.sendFile(file)
//                }
                "/h264" ->{
                    response!!.headers.set("Access-Control-Allow-Origin", "*")
                    response!!.headers.set("Connection", "close")
                    encode.releaseMediaCodec()
                    encode.initMediaCodec(response)
                }
                else -> {

                }
            }
        } else {
            // 针对的是静态资源的处理
            val filePath: String = ""
            if (filePath == null) {
                Log.d(TAG, "sd卡没有找到")
                response!!.send("sd卡没有找到")
                return
            }
            val file = File(filePath)
            if (file != null && file.exists()) {
                Log.d(TAG, "file path = " + file.getAbsolutePath())
                response!!.sendFile(file) //和nanohttpd不一样的地方
            } else {
                Log.d(TAG, "file path = " + file.getAbsolutePath().toString() + "的资源不存在")
            }
        }
    }

    private fun addCORSHeaders(requestOk: LocalHttpServer.Status, response: AsyncHttpServerResponse?) {
        response?.run {

        }
    }

    private fun checkUri(uri: String?): Boolean {
        return true
    }



}